package com.cgy.utils.thumb.builder;

import com.google.common.base.Preconditions;
import net.coobird.thumbnailator.Thumbnails;
import net.coobird.thumbnailator.filters.Watermark;
import net.coobird.thumbnailator.geometry.Coordinate;
import net.coobird.thumbnailator.geometry.Position;
import org.apache.commons.lang3.StringUtils;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;

/**
 * @author CH
 */
public class ThumbBuilder<T> {

    private String[] strings;
    private File[] files;
    private InputStream[] inputStreams;
    private URL[] urls;

    /********************输入 START**************************/
    private int width;
    private int height;
    private double scale;
    private boolean aspect;
    private double rotate;
    private Rectangle rectangle;
    private double quality;
    private String format = "jpeg";
    private Watermark watermaker;
    /********************输入 END**************************/
    /********************输出 START**************************/

    private File file;
    private String path;
    private File bufferImage;

    /********************输出 END**************************/

    public ThumbBuilder(File[] files) {
        this.files = files;
    }

    public ThumbBuilder(URL[] urls) {
        this.urls = urls;
    }

    public ThumbBuilder(InputStream[] inputStreams) {
        this.inputStreams = inputStreams;
    }

    public ThumbBuilder(String[] strings) {
        this.strings = strings;
    }

    /**
     * 按大小缩放
     * @param width
     * @param height
     * @return
     */
    public ThumbBuilder size(final int width, final int height) {
        Preconditions.checkArgument(width > 0);
        Preconditions.checkArgument(height > 0);
        this.width = width;
        this.height = height;
        return this;
    }

    /**
     * 按比例缩放
     * @param scale
     * @return
     */
    public ThumbBuilder scale(final double scale) {
        this.scale = scale;
        return this;
    }

    /**
     * 不按照比例，指定大小进行缩放
     * @param aspect
     * @return
     */
    public ThumbBuilder aspect(final boolean aspect) {
        this.aspect = aspect;
        return this;
    }

    /**
     * 旋转
     * @param rotate
     * @return
     */
    public ThumbBuilder rotate(final float rotate) {
        this.rotate = rotate;
        return this;
    }

    /**
     * 质量
     * @param quality
     * @return
     */
    public ThumbBuilder quality(final float quality) {
        this.quality = quality;
        return this;
    }

    /**
     * 格式
     * @param format
     * @return
     */
    public ThumbBuilder format(final String format) {
        this.format = format;
        return this;
    }

    /**
     * 裁剪
     * @return
     */
    public ThumbBuilder region(Rectangle rectangle) {
        this.rectangle = rectangle;
        return this;
    }
    /**
     * 裁剪
     * @return
     */
    public ThumbBuilder region(double x, double y, double x1, double y1) {
        Rectangle rectangle = new Rectangle();
        rectangle.setRect(x, y, x1 > x ? x1 - x : x - x1, y1 > y ? y1 - y : y - y1);
        this.rectangle = rectangle;
        return this;
    }
    /**
     * 裁剪
     * @return
     */
    public ThumbBuilder region(double x, double y, int width, int height) {
        Rectangle rectangle = new Rectangle();
        rectangle.setRect(x, y, width, height);
        this.rectangle = rectangle;
        return this;
    }
    /**
     * 水印
     * @return
     */
    public ThumbBuilder watchmaker(Watermark watermark) {
        this.watermaker = watermark;
        return this;
    }
    /**
     * 水印
     * @return
     */
    public ThumbBuilder watchmaker(Position position, BufferedImage bufferedImage, float opacity) {
        this.watermaker = new Watermark(position, bufferedImage, opacity);
        return this;
    }
    /**
     * 水印
     * @return
     */
    public ThumbBuilder watchmaker(Coordinate coordinate , BufferedImage bufferedImage, float opacity) {
        this.watermaker = new Watermark(coordinate, bufferedImage, opacity);
        return this;
    }
    /**
     * 水印
     * @return
     */
    public ThumbBuilder watchmaker(Position position, File image, float opacity) {
        Preconditions.checkArgument(image == null);
        BufferedImage read = null;
        try {
            read = ImageIO.read(image);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return watchmaker(position, read, opacity);
    }
    /**
     * 水印
     * @return
     */
    public ThumbBuilder watchmaker(Position position, String imageFile, float opacity) {
        Preconditions.checkArgument(StringUtils.isNotBlank(imageFile));
        BufferedImage read = null;
        try {
            read = ImageIO.read(new File(imageFile));
        } catch (IOException e) {
            e.printStackTrace();
        }
        return watchmaker(position, read, opacity);
    }
    /**
     * 水印
     * @return
     */
    public ThumbBuilder watchmaker(int x, int y, File image, float opacity) {
        Preconditions.checkArgument(image == null);
        BufferedImage read = null;
        try {
            read = ImageIO.read(image);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return watchmaker(x, y, read, opacity);
    }
    /**
     * 水印
     * @return
     */
    public ThumbBuilder watchmaker(int x, int y, String imageFile, float opacity) {
        Preconditions.checkArgument(StringUtils.isNotBlank(imageFile));
        BufferedImage read = null;
        try {
            read = ImageIO.read(new File(imageFile));
        } catch (IOException e) {
            e.printStackTrace();
        }
        return watchmaker(x, y, read, opacity);
    }
    /**
     * 水印
     * @return
     */
    public ThumbBuilder watchmaker(int x, int y , BufferedImage bufferedImage, float opacity) {
        Coordinate coordinate = new Coordinate(x, y);
        this.watermaker = new Watermark(coordinate, bufferedImage, opacity);
        return this;
    }

    /**
     * 输出
     * @param file
     * @return
     */
    public ThumbBuilder toFile(File file) {
        this.file = file;
        return this;
    }
    /**
     * 输出
     * @param path
     * @return
     */
    public ThumbBuilder toPath(String path) {
        this.path = path;
        return this;
    }
    /**
     * 输出
     * @return
     */
    public ThumbBuilder toBufferedImage(File file) {
        this.bufferImage = file;
        return this;
    }

    /**
     *
     * @return
     */
    public T build() {

        Thumbnails.Builder of = null;

        if(null != files && files.length > 0) {
            of = Thumbnails.of(files);
        } else if(null != inputStreams && inputStreams.length > 0) {
            of = Thumbnails.of(inputStreams);
        } else if(null != strings && strings.length > 0) {
            of = Thumbnails.of(strings);
        } else if(null != urls && urls.length > 0) {
            of = Thumbnails.of(urls);
        }

        if(aspect) {
            of.keepAspectRatio(true);
        }

        if(width > 0 && height > 0) {
            of.size(width, height);
        }
        if(scale > 0.0d) {
            of.scale(scale);
        }

        if(StringUtils.isNotBlank(format)) {
            of.outputFormat(format);
        }

        if(quality > 0d) {
            of.outputQuality(quality);
        }

        if(rotate > 0d) {
            of.rotate(rotate);
        }
        if(null != rectangle) {
            of.sourceRegion(rectangle);
        }

        if(null != watermaker) {
            of.watermark(watermaker);
        }

        try {
            if(null != file) {
                of.toFile(file);
                return (T)file;
            } else if(null != path) {
                of.toFile(path);
                return (T)path;
            } else if(null != bufferImage) {
                return (T) of.asBufferedImage();
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}
